import { monster } from './monster';
import { db, models } from '../../db';
import { getCardAttr } from './attr';
import { atkAction } from './atkAction';
import { recoverAction } from './recoverAction';
import { debuffAction } from './debuffAction';
import { buffAction } from './buffAction';
import {
  BattleCard,
  UserRole,
  Skill,
  SkillInfo,
  CardAction,
  BattleData,
  BattleReward,
  BattleResult,
  RoundEndAction,
} from '../types';

const { config_skill: ConfigSkillModel } = models;

let ownLineup: BattleCard[] = [];
let foeLineup: BattleCard[] = [];
let ownCards: BattleCard[] = [];
let foeCards: BattleCard[] = [];
let heroSkills: Skill[] = [];
let currentRound = 1;
let totalRound = 30;
let res: BattleData[] = [];
let resType = 0;
/**
 * 战斗逻辑
 */
export const Battle = (
  own: UserRole[],
  foe: UserRole[],
  type: number,
  ownName: string,
  foeName: string,
): Promise<BattleResult> => {
  return new Promise(async (resolve, reject) => {
    try {
      // 总回合数 boss 5 levels 30
      totalRound = type === 1 ? 5 : 30;
      // 1.初始化操作
      ownCards = own.map(v => {
        return {
          from: 'OWN',
          base: v,
          battle: {
            HP: v.hp,
            ATK: v.attack,
            DEF: v.defence,
            SPD: v.speed,
            HIT: 0,
            PRY: 0,
            CRIT: 0,
            CRIRES: 0,
            DMGADD: 0,
            DMGRED: 0,
            ANGRY: 0,
            CTRL: 0,
            STUN: 0,
            STUNRES: 0,
          },
          buff: [],
        };
      });
      ownLineup = JSON.parse(JSON.stringify(ownCards));

      // 敌方卡牌组
      foeCards = foe.map(v => {
        return {
          from: 'FOE',
          base: v,
          battle: {
            HP: v.hp,
            ATK: v.attack,
            DEF: v.defence,
            SPD: v.speed,
            HIT: type === 1 ? 1000 : 0,
            PRY: type === 1 ? -1000 : 0,
            CRIT: 0,
            CRIRES: 0,
            DMGADD: 0,
            DMGRED: 0,
            ANGRY: 0,
            CTRL: 0,
            STUN: 0,
            STUNRES: type === 1 ? 1000 : 0,
          },
          buff: [],
        };
      });
      foeLineup = JSON.parse(JSON.stringify(foeCards));

      const skillIds = [...own, ...foe]
        .map(v => {
          return [v.skill1, v.skill2, v.skill3].filter(v => v !== 0);
        })
        .flat();

      const setSkillIds = new Set(skillIds);

      const skills = await ConfigSkillModel.findAll({
        where: {
          id: [...setSkillIds],
        },
      });

      heroSkills = skills.map(v => {
        return {
          ...v.dataValues,
        };
      });
      res = [];

      // 2.第二步: 战前准备- 释放被动啥的

      // 3.第三步: 构建出手顺序 - 按照SPD排序
      for (let i = 1; i <= totalRound; i++) {
        // 回合开始 buff计算，替换战斗属性
        ownCards.forEach(v => {
          v.battle = getCardAttr(v);
        });

        foeCards.forEach(v => {
          v.battle = getCardAttr(v);
        });

        // 构建出手顺序
        const orderList = [...ownCards, ...foeCards].sort((a, b) => {
          return b.battle.SPD - a.battle.SPD;
        });
        currentRound = i;
        const action: CardAction[] = [];
        console.log(`第${currentRound}回合`);

        for (let j = 0; j < orderList.length; j++) {
          const card = orderList[j];
          const { from, base, battle } = card;
          console.log(`卡牌：${base.id}：${from}`);
          // 卡牌死亡跳过
          if (battle.HP === 0) {
            console.log(`卡牌：${base.id}：${from}`);
            continue;
          }
          // 卡牌被控制跳过
          if (battle.CTRL) {
            continue;
          }
          const cardActionData = await cardAction(orderList[j]);
          action.push(cardActionData!);
          if (ownCards.length === 0 || foeCards.length === 0) {
            if (ownCards.length === 0) {
              resType = 0;
            }
            if (foeCards.length === 0) {
              resType = 1;
            }
            if (type === 1) {
              resType = 2;
            }
            break;
          }
        }
        res.push({ round: currentRound, action: action, end: [] });
        if (ownCards.length === 0 || foeCards.length === 0) {
          break;
        }
        // 战斗未结束 - 给阵容中的所有人增加40战意
        const endAction: RoundEndAction[] = [];
        if (ownCards.length > 0) {
          ownCards.forEach(v => {
            v.battle.ANGRY = v.battle.ANGRY + 40 > 100 ? 100 : v.battle.ANGRY + 40;
            endAction.push({
              id: v.base.id,
              angry: v.battle.ANGRY,
            });
          });
        }
        if (foeCards.length > 0) {
          foeCards.forEach(v => {
            v.battle.ANGRY = v.battle.ANGRY + 40 > 100 ? 100 : v.battle.ANGRY + 40;
            endAction.push({
              id: v.base.id,
              angry: v.battle.ANGRY,
            });
          });
        }
        const nowRound = res.find(v => v.round === currentRound);
        if (nowRound) {
          nowRound.end = endAction;
        }
        // 回合结束 - 清除卡牌的buff
        ownCards.forEach(v => {
          const buff = v.buff;
          buff.forEach(bv => {
            bv.RND -= 1;
          });
          v.buff = buff.filter(v => v.RND > 0);
        });
        foeCards.forEach(v => {
          const buff = v.buff;
          buff.forEach(bv => {
            bv.RND -= 1;
          });
          v.buff = buff.filter(v => v.RND > 0);
        });
      }
    } catch (error: any) {
      const { message } = error;
      console.log(message);
    } finally {
      let totalDmg = 0;
      res.forEach(v => {
        const { action } = v;
        action.forEach(av => {
          const { from, target } = av;
          if (from === 'OWN') {
            target.forEach(tv => {
              const { dmg } = tv;
              totalDmg += dmg;
            });
          }
        });
      });
      const reward: BattleReward[] = [];
      if (type === 1) {
        const count = Math.floor(totalDmg / 10000);
        if (count > 0) {
          reward.push({ id: 1015, count });
        }
      }
      resolve({
        type: resType,
        totalDmg,
        ownName,
        foeName,
        own: ownLineup,
        foe: foeLineup,
        battle: res,
        reward: reward,
      });
    }
  });
};

const cardAction = (card: BattleCard) => {
  // 1.谁出手
  const { base, battle } = card;
  const { id, heroName } = base;
  console.log(`出手：${heroName}-${id}`);
  console.log(`属性：${JSON.stringify(battle)}`);
  // 2.使用什么技能
  const skl = getSkill(card);
  console.log(`技能：${skl.skill.name}`);
  // 3.对谁出手
  const target = monster(card, skl.skill, ownCards, foeCards);
  console.log(`目标：${target.map(v => v.base.id)}`);
  // 4.出手执行
  return skillAction(card, skl, target);
};

const getSkill = (card: BattleCard): SkillInfo => {
  const { base, battle } = card;
  const { ANGRY } = battle;
  const { skill1, skill2 } = base;

  const skillId = ANGRY >= 100 ? skill2 : skill1;

  return { skill: heroSkills.find(v => v.id === skillId)!, type: ANGRY >= 100 ? 2 : 1 };
};

const skillAction = (card: BattleCard, skl: SkillInfo, target: BattleCard[]) => {
  const { action } = skl.skill;

  switch (action) {
    case 1:
      return atkAction(ownCards, foeCards, card, skl, target);
    case 2:
      return recoverAction(card, skl, target);
    case 3:
      return debuffAction(card, skl, target);
    case 4:
      return buffAction(card, skl, target);
  }
};
